home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / wais / waisgate / HTWSRC.c < prev    next >
C/C++ Source or Header  |  1995-05-09  |  9KB  |  416 lines

  1. /*            Parse WAIS Source file            HTWSRC.c
  2. **            ======================
  3. **
  4. **    This module parses a stream with WAIS source file
  5. **    format information on it and creates a structured stream.
  6. **    That structured stream is then converted into whatever.
  7. **
  8. */
  9.  
  10. #include "HTWSRC.h"
  11.  
  12.  
  13. #include <sys/types.h>
  14. #include <sys/stat.h>
  15. #include <stdio.h>
  16. #include "HTML.h"
  17.  
  18. #include "HTUtils.h"
  19. #include "tcp.h"
  20. #include "HTParse.h"
  21.  
  22. #define BIG 10000        /* Arbitrary limit to value length */
  23. #define PARAM_MAX BIG
  24. #define CACHE_PERIOD (7*86400)    /* Time to keep .src file in seconds */
  25.  
  26. #define HEX_ESCAPE '%'
  27.  
  28. struct _HTStructured {
  29.     CONST HTStructuredClass *    isa;
  30.     /* ... */
  31. };
  32.  
  33. #define PUTC(c) (*me->targetClass.put_character)(me->target, c)
  34. #define PUTS(s) (*me->targetClass.put_string)(me->target, s)
  35. #define START(e) (*me->targetClass.start_element)(me->target, e, 0, 0)
  36. #define END(e) (*me->targetClass.end_element)(me->target, e)
  37.  
  38.  
  39. /*    Here are the parameters which can be specified in a  source file
  40. */
  41. PRIVATE CONST char* par_name[] = {
  42.     "version", 
  43.     "ip-address",
  44. #define PAR_IP_NAME 2
  45.     "ip-name", 
  46. #define PAR_TCP_PORT 3
  47.     "tcp-port", 
  48. #define PAR_DATABASE_NAME 4
  49.     "database-name",
  50. #define PAR_COST 5
  51.     "cost", 
  52. #define PAR_COST_UNIT 6
  53.     "cost-unit", 
  54. #define PAR_FREE 7
  55.     "free",    
  56. #define PAR_MAINTAINER 8
  57.     "maintainer",     
  58. #define PAR_DESCRIPTION 9
  59.     "description",     
  60.     "source",
  61.     0,                /* Terminate list */
  62. #define PAR_COUNT 11
  63. } ;
  64.  
  65.  
  66. enum tokenstate { beginning, before_tag, colon, before_value,
  67.         value, quoted_value, done };
  68.  
  69.  
  70. /*        Stream Object
  71. **        ------------
  72. **
  73. **    The target is the structured stream down which the
  74. **    parsed results will go.
  75. **
  76. **    all the static stuff below should go in here to make it reentrant
  77. */
  78.  
  79. struct _HTStream {
  80.     CONST HTStreamClass *    isa;
  81.     HTStructured *        target;
  82.     HTStructuredClass    targetClass;
  83.     char *            par_value[PAR_COUNT];
  84.     enum tokenstate     state;
  85.     char             param[BIG+1];
  86.     int            param_number;
  87.     int            param_count;
  88. };
  89.  
  90.  
  91.  
  92.  
  93. PUBLIC CONST char * hex = "0123456789ABCDEF";
  94.  
  95. /*    Decode one hex character
  96. */
  97.  
  98. PUBLIC char from_hex ARGS1(char, c)
  99. {
  100.     return           (c>='0')&&(c<='9') ? c-'0'
  101.             : (c>='A')&&(c<='F') ? c-'A'+10
  102.             : (c>='a')&&(c<='f') ? c-'a'+10
  103.             :               0;
  104. }
  105.  
  106.  
  107. /*            State machine
  108. **            -------------
  109. **
  110. ** On entry,
  111. **    me->state    is a valid state (see WSRC_init)
  112. **    c        is the next character
  113. ** On exit,
  114. **     returns    1    Done with file
  115. **        0    Continue. me->state is updated if necessary.
  116. **        -1    Syntax error error
  117. */
  118.  
  119.  
  120. /*        Treat One Character
  121. **        -------------------
  122. */
  123. PRIVATE void WSRCParser_put_character ARGS2(HTStream*, me, char, c)
  124. {
  125.     switch (me->state) {
  126.     case beginning:
  127.         if (c=='(') me->state = before_tag;
  128.     break;
  129.     
  130.     case before_tag:
  131.         if (c==')') {
  132.         me->state = done;
  133.         return;            /* Done with input file */
  134.     } else if (c==':') {
  135.         me->param_count = 0;
  136.         me->state = colon;
  137.     }                /* Ignore other text */
  138.     break;
  139.  
  140.     case colon:
  141.         if (WHITE(c)) {
  142.         me->param[me->param_count++] = 0;    /* Terminate */
  143.         for(me->param_number = 0; par_name[me->param_number]; me->param_number++) {
  144.         if (0==strcmp(par_name[me->param_number], me->param)) {
  145.             break;
  146.         }
  147.         }
  148.         if (!par_name[me->param_number]) {    /* Unknown field */
  149.             if (TRACE) fprintf(stderr,
  150.             "WAISGate: Unknown field `%s' in source file\n",
  151.             me->param);
  152.         me->state = before_tag;    /* Could be better ignore */
  153.         return;
  154.         }
  155.         me->state = before_value;
  156.     } else {
  157.         if (me->param_count < PARAM_MAX)  me->param[me->param_count++] = c;
  158.     }
  159.     break;
  160.     
  161.     case before_value:
  162.         if (c==')') {
  163.         me->state = done;
  164.         return;            /* Done with input file */
  165.     }
  166.     if (WHITE(c)) return;        /* Skip white space */
  167.     me->param_count = 0;
  168.     if (c=='"') {
  169.         me->state = quoted_value;
  170.         break;
  171.     }
  172.     me->state = (c=='"') ? quoted_value : value;
  173.     me->param[me->param_count++] = c;    /* Don't miss first character */
  174.     break;
  175.  
  176.     case value:
  177.         if (WHITE(c)) {
  178.         me->param[me->param_count] = 0;
  179.         StrAllocCopy(me->par_value[me->param_number], me->param);
  180.         me->state = before_tag;
  181.     } else {
  182.         if (me->param_count < PARAM_MAX)  me->param[me->param_count++] = c;
  183.     }
  184.     break;
  185.  
  186.     case quoted_value:
  187.         if (c=='"') {
  188.         me->param[me->param_count] = 0;
  189.         StrAllocCopy(me->par_value[me->param_number], me->param);
  190.         me->state = before_tag;
  191.     } else {
  192.         if (me->param_count < PARAM_MAX)  me->param[me->param_count++] = c;
  193.     }
  194.     break;
  195.     
  196.     case done:                /* Ignore anything after EOF */
  197.     return;
  198.  
  199.     } /* switch me->state */
  200. }
  201.  
  202.  
  203. /*            Output equivalent HTML
  204. **            ----------------------
  205. **
  206. */
  207.  
  208. void give_parameter ARGS2(HTStream *, me, int, p)
  209. {
  210.     PUTS(par_name[p]);
  211.     if (me->par_value[p]) {
  212.     PUTS(": ");
  213.     PUTS(me->par_value[p]);
  214.     PUTS("; ");
  215.     } else {
  216.         PUTS(" NOT GIVEN in source file; ");
  217.     }
  218. }
  219.  
  220.  
  221. /*            Generate Outout
  222. **            ===============
  223. */
  224. void WSRC_gen_html ARGS1(HTStream *, me)
  225.  
  226. {
  227.     if (me->par_value[PAR_DATABASE_NAME]) {
  228.     char * shortname = 0;
  229.     int l;
  230.     StrAllocCopy(shortname, me->par_value[PAR_DATABASE_NAME]);
  231.     l = strlen(shortname);
  232.     if ( l > 4 && !strcasecomp(shortname + l -4, ".src")) {
  233.         shortname[l-4] = 0;    /* Chop of .src -- boring! */
  234.     }
  235.     
  236.     START(HTML_TITLE);
  237.     PUTS(shortname);
  238.     PUTS(" index");
  239.     END(HTML_TITLE);
  240.     
  241.     START(HTML_H1);
  242.     PUTS(shortname);
  243.     PUTS(" index");
  244.     END(HTML_H1);
  245.     }
  246.     
  247.     START(HTML_DL);        /* Definition list of details */
  248.     
  249.     START(HTML_DT);
  250.     PUTS("Access links");
  251.     START(HTML_DD);
  252.     if (me->par_value[PAR_IP_NAME] &&
  253.     me->par_value[PAR_DATABASE_NAME]) {
  254.  
  255.     char WSRC_address[256];
  256.     char * www_database;
  257.     www_database = HTEscape(me->par_value[PAR_DATABASE_NAME], URL_XALPHAS);
  258.     sprintf(WSRC_address, "wais://%s:%s/%s",
  259.         me->par_value[PAR_IP_NAME],
  260.         me->par_value[PAR_TCP_PORT] ? me->par_value[PAR_TCP_PORT] : "210",
  261.         www_database);
  262.     
  263.     HTStartAnchor(me->target, NULL, WSRC_address);
  264.     PUTS("Direct access");
  265.     END(HTML_A);
  266.     
  267.     PUTS(" or ");
  268.     
  269.     sprintf(WSRC_address, "http://info.cern.ch:8001/%s:%s/%s",
  270.         me->par_value[PAR_IP_NAME],
  271.         me->par_value[PAR_TCP_PORT] ? me->par_value[PAR_TCP_PORT] : "210",
  272.         www_database);
  273.     HTStartAnchor(me->target, NULL, WSRC_address);
  274.     PUTS("Through CERN gateway");
  275.     END(HTML_A);
  276.     
  277.     free(www_database);
  278.     
  279.     } else {
  280.         give_parameter(me, PAR_IP_NAME);
  281.         give_parameter(me, PAR_IP_NAME);
  282.     }
  283.  
  284.     if (me->par_value[PAR_MAINTAINER]) {
  285.     START(HTML_DT);
  286.     PUTS("Maintainer");
  287.     START(HTML_DD);
  288.     PUTS(me->par_value[PAR_MAINTAINER]);
  289.     }
  290.     START(HTML_DT);
  291.     PUTS("Host");
  292.     START(HTML_DD);
  293.     PUTS(me->par_value[PAR_IP_NAME]);
  294.  
  295.     END(HTML_DL);
  296.  
  297.     START(HTML_PRE);        /* Preformatted description */
  298.     PUTS(me->par_value[PAR_DESCRIPTION]);
  299.     END(HTML_PRE);
  300.  
  301.     (*me->targetClass.end_document)(me->target);
  302.     (*me->targetClass.free)(me->target);
  303.     
  304.     return;
  305. } /* generate html */
  306.  
  307.  
  308. PRIVATE void WSRCParser_put_string ARGS2(HTStream *, context, CONST char*, str)
  309. {
  310.     CONST char *p;
  311.     for(p=str; *p; p++)
  312.         WSRCParser_put_character(context, *p);
  313. }
  314.  
  315.  
  316. PRIVATE void WSRCParser_write ARGS3(
  317.         HTStream *,     context,
  318.         CONST char*,     str,
  319.         int,         l)
  320. {
  321.     CONST char *p;
  322.     CONST char *e = str+l;
  323.     for(p=str; p<e; p++)
  324.         WSRCParser_put_character(context, *p);
  325. }
  326.  
  327.  
  328. PRIVATE void WSRCParser_free ARGS1(HTStream *, me)
  329. {
  330.     WSRC_gen_html(me);
  331.     {
  332.     int p;
  333.     for(p=0; par_name[p]; p++) {    /* Clear out old values */
  334.         if (me->par_value[p]) {
  335.         free(me->par_value[p]);
  336.         }
  337.     }
  338.     }
  339.     free(me);
  340. }
  341.  
  342. PRIVATE void WSRCParser_end_document ARGS1(HTStream *, me)
  343. {
  344. /* Nothing */
  345. }
  346.  
  347.  
  348. /*        Stream subclass        -- method routines
  349. **        ---------------
  350. */
  351.  
  352. HTStreamClass WSRCParserClass = {
  353.     "WSRCParser",
  354.     WSRCParser_free,
  355.     WSRCParser_end_document,
  356.     WSRCParser_put_character,
  357.      WSRCParser_put_string,
  358.     WSRCParser_write
  359.  
  360. };
  361.  
  362. /*        Converter from WAIS Source to whatever
  363. **        --------------------------------------
  364. */
  365. PUBLIC HTStream* HTWSRCConvert ARGS3(
  366.     HTPresentation *,    pres,
  367.     HTParentAnchor *,    anchor,    
  368.     HTStream *,        sink)
  369. {
  370.     HTStream * me = (HTStream*) malloc(sizeof(*me));
  371.     if (!me) outofmem(__FILE__, "HTWSRCConvert");
  372.  
  373.     me->isa = &WSRCParserClass;
  374.     me->target = HTML_new(anchor, pres->rep_out, sink);
  375.     me->targetClass = *me->target->isa;
  376.  
  377.     {
  378.     int p;
  379.     for(p=0; p < PAR_COUNT; p++) {    /* Clear out parameter values */
  380.         me->par_value[p] = 0;
  381.     }
  382.     }
  383.     me->state = beginning;
  384.  
  385.     return me;
  386. }
  387.  
  388.  
  389.  
  390. /*            Main Program    -- NOT USED -- HISTORICAL
  391. **            ============
  392. **
  393. ** Takes .src on stdin and makes cache file.
  394. */
  395.  
  396. #ifdef TEST
  397. PUBLIC int WWW_TraceFlag = 0;
  398. int main(int argc, char *argv[])
  399. {
  400.     char c;
  401.     
  402.     if (argc>1) 
  403.         WWW_TraceFlag = 0==strcmp(argv[1], "-v") ? 1 : 0;
  404.     
  405.     for(WSRC_init(); (c=getc(stdin)) != EOF; ) {
  406.     if (WSRC_treat(c)) break;
  407.         /* fprintf(stderr, "char '%c', state = %d\n", c, me->state); */
  408.     }
  409.     WSRC_gen_html();
  410.         
  411.     return 0;
  412.     
  413. } /* main */
  414. #endif
  415.  
  416.